#define RGB_RESET 0x03C6
#define RGB_READ 0x03C7
#define RGB_WRITE 0x03C8
#define RGB_DATA 0x03C9 

const int VGA_SCREEN_X_MAX = 320;
const int VGA_SCREEN_Y_MAX = 200;
static const int VIDEO_ADDR = 0xA0000 ;

 const int _A[5][5]={{0,0,1,0,0},
				  {0,1,0,1,0},
				  {1,1,1,1,1},
				  {1,0,0,0,1},
                                  {1,0,0,0,1}};
const int _B[5][5]={{1,1,1,1,0},
									   {1,0,0,0,1},
									   {1,1,1,1,0},
									   {1,0,0,0,1},
									   {1,1,1,1,0}};	
const int _C[5][5]={{0,1,1,1,0},
									   {1,0,0,0,1},
									   {1,0,0,0,0},
									   {1,0,0,0,1},
									   {0,1,1,1,0}};
const int _D[5][5]={{1,1,1,1,0},
									   {1,0,0,0,1},
									   {1,0,0,0,1},
									   {1,0,0,0,1},
									   {1,1,1,1,0}};
const int _E[5][5]={{1,1,1,1,1},
									   {1,0,0,0,0},
									   {1,1,1,1,1},
									   {1,0,0,0,0},
									   {1,1,1,1,1}};
const int _F[5][5]={{1,1,1,1,1},
									   {1,0,0,0,0},
									   {1,1,1,1,0},
									   {1,0,0,0,0},
									   {1,0,0,0,0}};
const int _G[5][5]={{1,1,1,1,0},
									   {1,0,0,0,1},
									   {1,0,0,0,0},
									   {1,0,0,1,1},
									   {0,1,1,1,1}};
const int _H[5][5]={{1,0,0,0,1},
									   {1,0,0,0,1},
									   {1,1,1,1,1},
									   {1,0,0,0,1},
									   {1,0,0,0,1}};
const int _I[5][5]={{0,1,1,1,0},
									   {0,0,1,0,0},
									   {0,0,1,0,0},
									   {0,0,1,0,0},
									   {0,1,1,1,0}};
const int _J[5][5]={{0,0,0,1,0},
									   {0,0,0,1,0},
									   {0,0,0,1,0},
									   {1,0,0,1,0},
									   {0,1,1,0,0}};
									   	
const int _K[5][5]={{1,0,0,0,1},
									   {1,0,0,1,0},
									   {1,1,1,0,0},
									   {1,0,0,1,1},
									   {1,0,0,0,1}};
									   	
const int _L[5][5]={{1,0,0,0,0},
									   {1,0,0,0,0},
									   {1,0,0,0,0},
									   {1,0,0,0,0},
									   {1,1,1,1,1}};
									   	
const int _M[5][5]={{1,0,0,0,1},
									   {1,1,0,1,1},
									   {1,0,1,0,1},
									   {1,0,1,0,1},
									   {1,0,0,0,1}};
									   	
const int _N[5][5]={{1,0,0,0,1},
									   {1,1,0,0,1},
									   {1,0,1,0,1},
									   {1,0,0,1,1},
									   {1,0,0,0,1}};	

const int _O[5][5]={{0,1,1,1,0},
									   {1,0,0,0,1},
									   {1,0,0,0,1},
									   {1,0,0,0,1},
									   {0,1,1,1,0}};	

const int  _P[5][5]={{1,1,1,1,0},
									   {1,0,0,0,1},
									   {1,1,1,1,0},
									   {1,0,0,0,0},
									   {1,0,0,0,0}};

const int  _Q[5][5]={{0,1,1,1,0},
									   {1,0,0,0,1},
									   {1,0,0,0,1},
									   {0,1,1,1,0},
									   {0,0,1,0,0}};										

const int  _R[5][5]={{1,1,1,1,0},
									   {1,0,0,0,1},
									   {1,1,1,1,0},
									   {1,0,0,1,0},
									   {1,0,0,0,1}};	

const int  _S[5][5]={{0,0,1,1,0},
									   {0,1,0,0,1},
									   {0,0,1,0,0},
									   {1,0,0,1,0},
									   {0,1,1,0,0}};	
									   										   	
const int  _T[5][5]={{1,1,1,1,1},
									   {0,0,1,0,0},
									   {0,0,1,0,0},
									   {0,0,1,0,0},
									   {0,0,1,0,0}};	

const int  _U[5][5]={{1,0,0,0,1},
									   {1,0,0,0,1},
									   {1,0,0,0,1},
									   {1,0,0,0,1},
									   {0,1,1,1,0}};										   										   	
									   	
const int  _V[5][5]={{1,0,0,0,1},
									   {1,0,0,0,1},
									   {1,0,0,0,1},
									   {0,1,0,1,0},
									   {0,0,1,0,0}};	
									   	
const int  _W[5][5]={{1,0,0,0,1},
									   {1,0,1,0,1},
									   {1,0,1,0,1},
									   {1,0,1,0,1},
									   {0,1,0,1,0}};	
									   	
const int  _X[5][5]={{1,0,0,0,1},
									   {0,1,0,1,0},
									   {0,0,1,0,0},
									   {0,1,0,1,0},
									   {1,0,0,0,1}};

const int  _Y[5][5]={{1,0,0,0,1},
									   {0,1,0,1,0},
									   {0,0,1,0,0},
									   {0,0,1,0,0},
									   {0,0,1,0,0}};									  										   										   										   										   	

const int  _Z[5][5]={{1,1,1,1,1},
	                       {0,0,0,1,0},
			       {0,0,1,0,0},
			       {0,1,0,0,0},
			       {1,1,1,1,1}};
	
const int  _1[5][5]={{0,0,1,0,0},
	                       {0,1,1,0,0},
			       {0,0,1,0,0},
			       {0,0,1,0,0},
			       {0,1,1,1,0}};	

const int  _2[5][5]={{0,1,1,1,1},
	                       {1,0,0,0,1},
			       {0,0,0,1,0},
			       {0,0,1,0,0},
			       {1,1,1,1,1}};	

const int  _3[5][5]={{0,1,1,1,0},
	                       {0,0,0,0,1},
			       {0,1,1,1,0},
			       {0,0,0,0,1},
			       {0,1,1,1,0}};	

const int  _4[5][5]={{0,0,0,1,0},
	                       {0,0,1,1,0},
			       {0,1,0,1,0},
			       {1,1,1,1,1},
			       {0,0,0,1,0}};	

const int  _5[5][5]={{1,1,1,1,1},
	                       {1,0,0,0,0},
			       {1,1,1,1,0},
			       {0,0,0,0,1},
			       {1,1,1,1,0}};	

const int  _6[5][5]= {{0,1,1,1,0},
	                       {1,0,0,0,0},
			       {1,1,1,1,0},
			       {1,0,0,0,1},
			       {0,1,1,1,0}};	

const int  _7[5][5]={{1,1,1,1,1},
	                       {0,0,0,1,0},
			       {0,0,1,0,0},
			       {0,1,0,0,0},
			       {1,0,0,0,0}};	

const int  _8[5][5]={{0,1,1,1,0},
	                       {1,0,0,0,1},
			       {0,1,1,1,0},
			       {1,0,0,0,1},
			       {0,1,1,1,0}};

const int  _9[5][5]={{0,1,1,1,0},
	                       {1,0,0,0,1},
			       {0,1,1,1,1},
			       {0,0,0,0,1},
			       {0,1,1,1,0}};	

const int  _0[5][5]={{0,1,1,1,0},
	                       {1,0,0,0,1},
			       {1,0,0,0,1},
			       {1,0,0,0,1},
			       {0,1,1,1,0}};

const int _minimize[5][5]={{0,0,0,0,0},
	                          {0,0,0,0,0},
			          {0,1,1,1,0},
			          {0,0,0,0,0},			          {0,0,0,0,0}};	

const int _maximize[5][5]={{0,0,0,0,0},
	                          {0,0,1,0,0},
			          {0,1,0,1,0},
			          {1,0,0,0,1},			          {0,0,0,0,0}};									   	
									   	
void set_palette(int index, int red, int green, int blue)
{
   out_byte(RGB_RESET, 0xFF); //Prepare the VGA card for the color change
   out_byte(RGB_WRITE, (unsigned char)index); //Tell which palette register to write to
      //The following values can be anywhere from 0 to 63
   out_byte(RGB_DATA, (unsigned char)red); //change the red value
   out_byte(RGB_DATA, (unsigned char)green); //change the green value
   out_byte(RGB_DATA, (unsigned char)blue); //change the blue value
} 

// 色调合成函数
unsigned short vesa_compond_rgb( unsigned char r , unsigned char g , unsigned char b )
{
  union{
    unsigned int color ;
    struct{
      unsigned char b : 5 ;
      unsigned char g : 6 ;
      unsigned char r : 5 ;
    } ;
  } u ;
  u.r = r % 32 ;
  u.g = g % 32 ;
  u.b = b % 32 ;
  return u.color ;
}

// 画点函数
void vesa_draw_point( unsigned int x , unsigned int y , unsigned short color )
{  
  unsigned int x_max = VGA_SCREEN_X_MAX - 1 ; // 每行像素数
  unsigned int y_max = VGA_SCREEN_Y_MAX - 1 ; // 每列像素数
  unsigned char temp = (unsigned char)color;
  // 防止越界
  if( x > x_max ){
    return ;
  }
  if( y > y_max ){
    return ;
  }

  // 取得显存线性地址
  unsigned char *video = ( unsigned char * )( VIDEO_ADDR ) ;

  // 计算点的偏移量
  int offset = y * ( x_max + 1 ) + x ;  
  *(unsigned char*)( video + offset ) = temp ;
}

// 取得指定点色彩
unsigned short vesa_get_point_color( unsigned int x , unsigned int y )
{
  unsigned int x_max = VGA_SCREEN_X_MAX - 1 ; // 每行像素数
  unsigned int y_max = VGA_SCREEN_Y_MAX - 1 ; // 每列像素数

  if( x > x_max ){
  // 防止越界
    x = x_max ;
  }
  if( y > y_max ){
    y = y_max ;
  }

  // 取得显存线性地址
  unsigned short *video = ( unsigned short * )( VIDEO_ADDR ) ;

  // 计算点的偏移量
  unsigned int offset = y * ( x_max + 1 ) + x ;  
  return *( video + offset ) ;
}

// 矩形填充函数
void vesa_fill_rect( unsigned int x1 , unsigned int y1 , unsigned int x2 , unsigned int y2 , unsigned int color )
{
  int x,  y;
  for( x = x1 ; x < x2 + 1 ; ++x ){
    for( y = y1 ; y < y2 + 1 ; ++y ){
      vesa_draw_point( x , y , color ) ;
    }
  }
}

// 画空心矩形函数
void vesa_draw_rect( unsigned int x1 , unsigned int y1 , unsigned int x2 , unsigned int y2 , unsigned int color )
{
	int x,y;
	for(x=x1;x<x2;x++)
	{
		vesa_draw_point(x,y1,color);
		vesa_draw_point(x,y2,color);
	}
	for(y=y1;y<y2;y++)
	{
		vesa_draw_point(x1,y,color);
		vesa_draw_point(x2,y,color);
	}
}

// 清屏函数
void vesa_clean_screen( unsigned short color )
{
  vesa_fill_rect( 0 , 0 , VGA_SCREEN_X_MAX - 1 , VGA_SCREEN_Y_MAX - 1 , color ) ;
}


//画矩阵
void vesa_paint_matrix (unsigned short *matrix[], unsigned int x_ltop, unsigned int y_ltop, unsigned int height, unsigned int width)
{
  unsigned int i, j;
  for (i = 0; i < height; i++){
    for (j = 0; j < width; j++){
      vesa_draw_point(j + x_ltop, i + y_ltop, matrix[i][j]);
    }
  }
}


//画矩形
/*void vesa_paint_rectangle(unsigned int x_ltop, unsigned int y_l_top, unsigned int x_rbottom, unsigned int y_rbottom, unsigned short color)
{
  int i, j;
  for (i = )
  vesa_draw_point ()
}
*/

// 画字母底层
void vesa_paint_letter1(int let[5][5], unsigned int x,unsigned int y, unsigned short color)
{
	int i=0,j=0;
	for(i=0;i<5;i++)
		for(j=0;j<5;j++)
		{
			if(let[i][j]==1) vesa_draw_point(x+j,y+i,color);
			else continue;
		}
}

//画字母
void vesa_paint_letter(char letter,unsigned int x,unsigned int y, unsigned short color)
{
	switch(letter)
	{
		case 'A': vesa_paint_letter1(_A,x,y,color); break;
		case 'B': vesa_paint_letter1(_B,x,y,color); break;
		case 'C': vesa_paint_letter1(_C,x,y,color);break;
		case 'D': vesa_paint_letter1(_D,x,y,color);break;
		case 'E': vesa_paint_letter1(_E,x,y,color);break;
		case 'F': vesa_paint_letter1(_F,x,y,color);break;
		case 'G': vesa_paint_letter1(_G,x,y,color);break;
		case 'H': vesa_paint_letter1(_H,x,y,color);break;
		case 'I': vesa_paint_letter1(_I,x,y,color);break;
		case 'J': vesa_paint_letter1(_J,x,y,color);break;
		case 'K': vesa_paint_letter1(_K,x,y,color);break;
		case 'L': vesa_paint_letter1(_L,x,y,color);break;
		case 'M': vesa_paint_letter1(_M,x,y,color);break;
		case 'N': vesa_paint_letter1(_N,x,y,color);break;
		case 'O': vesa_paint_letter1(_O,x,y,color);break;
		case 'P': vesa_paint_letter1(_P,x,y,color);break;
		case 'Q': vesa_paint_letter1(_Q,x,y,color);break;
		case 'R': vesa_paint_letter1(_R,x,y,color);break;
		case 'S': vesa_paint_letter1(_S,x,y,color);break;
		case 'T': vesa_paint_letter1(_T,x,y,color);break;
		case 'U': vesa_paint_letter1(_U,x,y,color);break;
		case 'V': vesa_paint_letter1(_V,x,y,color);break;
		case 'W': vesa_paint_letter1(_W,x,y,color);break;
		case 'X': vesa_paint_letter1(_X,x,y,color);break;
		case 'Y': vesa_paint_letter1(_Y,x,y,color);break;
		case 'Z': vesa_paint_letter1(_Z,x,y,color);break;
		case '1': vesa_paint_letter1(_1,x,y,color);break;
		case '2': vesa_paint_letter1(_2,x,y,color);break;
		case '3': vesa_paint_letter1(_3,x,y,color);break;
		case '4': vesa_paint_letter1(_4,x,y,color);break;
		case '5': vesa_paint_letter1(_5,x,y,color);break;
		case '6': vesa_paint_letter1(_6,x,y,color);break;
		case '7': vesa_paint_letter1(_7,x,y,color);break;
		case '8': vesa_paint_letter1(_8,x,y,color);break;
		case '9': vesa_paint_letter1(_9,x,y,color);break;
		case '0': vesa_paint_letter1(_0,x,y,color);break;
	}
}

void vesa_paint_number(int n,unsigned int x,unsigned int y, unsigned short color)
{
	switch(n)
	{
		case 0: vesa_paint_letter1(_0,x,y,color);break;
		case 1: vesa_paint_letter1(_1,x,y,color);break;
		case 2: vesa_paint_letter1(_2,x,y,color);break;
		case 3: vesa_paint_letter1(_3,x,y,color);break;
		case 4: vesa_paint_letter1(_4,x,y,color);break;
		case 5: vesa_paint_letter1(_5,x,y,color);break;
		case 6: vesa_paint_letter1(_6,x,y,color);break;
		case 7: vesa_paint_letter1(_7,x,y,color);break;
		case 8: vesa_paint_letter1(_8,x,y,color);break;
		case 9: vesa_paint_letter1(_9,x,y,color);break;
	}
}

void vesa_paint_icon(unsigned int ictype, unsigned int x,unsigned int y,unsigned short color)
{
	switch(ictype)
	{
		case 2: vesa_paint_letter1(_maximize,x,y,color);break;
		case 3: vesa_paint_letter1(_minimize,x,y,color);break;
	}
}
void vesa_paint_string(char str[10], unsigned int x, unsigned int y, unsigned short color,unsigned int n)
{
	int i=0;
	int j=0;
	for(i=0;i<n;i++)
	{
		if(x+j*6>315) 
		{
			y=y+6;
			x=0;
			j=0;
		}
		vesa_paint_letter(str[i],x+j*6,y,color);
		j++;
	}
}
















      
